//
//  WATFFTVManager.swift
//  WiFiFaster
//
//  Created by one on 2024/1/4.
//

import UIKit
import NetworkExtension
import OSLog
let watf_proxyID = "com.zxcz.yyer.zdv.WATFFTVTunnel"
let watf_serverAddress = "127.0.0.1"
let watf_ftvStateChange_noti = NSNotification.Name.NEVPNStatusDidChange
let watf_ftvLocalUpdate_noti = NSNotification.Name.init("watf_ftvLocalUpdate_noti")
let watf_ftvConnect_noti = NSNotification.Name.init("watf_ftvConnect_noti")
func WATFPrintOpt(watf_cot: String) {
    os_log("%{public}s", watf_cot)
}
extension WATFManager {
    fileprivate func watf_getRuleConf() -> String{
        let Path = Bundle.main.path(forResource: "WATFFTVRule", ofType: "conf")
        let Data = try? Foundation.Data(contentsOf: URL(fileURLWithPath: Path!))
        let str = String(data: Data!, encoding: String.Encoding.utf8)!
        return str
    }
    // 创建 ftv 管理对象
    func watf_initftvMangerObjectAction() -> NETunnelProviderManager {
        let watf_protocol = NETunnelProviderProtocol()
        watf_protocol.providerBundleIdentifier = watf_proxyID
        
        watf_protocol.serverAddress = "WiFi Faster"
        let watf_ftvManager = NETunnelProviderManager()
        watf_ftvManager.protocolConfiguration = watf_protocol
        watf_ftvManager.localizedDescription = "WiFi Faster"
        watf_ftvManager.isEnabled = true
        return watf_ftvManager
    }
    func watf_configFTVprovider() -> [String: NSObject] {
        let watf_serModel = watf_getSelectFTVModel()
        guard let watf_serModel = watf_serModel else {return [:]}
        return ["watf_options": [
            "watf_address": watf_serModel.watf_address ,
            "watf_port": watf_serModel.watf_port  ,
            "watf_method": watf_serModel.watf_method  ,
            "watf_password": watf_serModel.watf_password ,
            "watf_ruletConf": watf_getRuleConf() ] as NSObject
        ]
    }
    //MARK: - ftv 权限
    func watf_ftvAuthAction(watf_complete:((NETunnelProviderManager?, Error?) -> ())? = nil) {
        NETunnelProviderManager.loadAllFromPreferences { (watf_mangers, watf_error) in
            if let watf_error = watf_error {
                watf_complete?(nil, watf_error)
                return
            }
            guard let watf_mangers = watf_mangers, let watf_manger = watf_mangers.first else {
                self.watf_ftvAuth = false
                watf_complete?(nil, nil)
                return
            }
            self.watf_ftvAuth = true
            self.watf_ftvManager = watf_manger
            watf_complete?(watf_manger, nil)
        }
    }
    //MARK: - 开始连接
    func watf_startConnect(watf_ftvModel: WATFFTVTempModel? = nil, watf_complete: ((Bool)->())? = nil) {
        guard let _ = watf_ftvModel else {
            watf_complete?(false)
            return }
        watf_curFTVModel = watf_ftvModel
        watf_ftvAuthAction { [self] watf_manager, watf_error in
            if let _ = watf_error {
                watf_complete?(false)
                return
            }
            guard let watf_manager = watf_manager else {
                
                let watf_newManager = watf_initftvMangerObjectAction()
                self.watf_ftvManager = watf_newManager
                
                watf_newManager.saveToPreferences { err in
                    if let _ = err {
                        watf_complete?(false)
                        return
                    }
                    
                    watf_newManager.loadFromPreferences { err in
                        if let _ = err {
                            watf_complete?(false)
                            return
                        }
                        //                        if watf_newManager.connection.status == .disconnected || watf_newManager.connection.status == .invalid {
                        do {
                            watf_complete?(true)
                            try watf_newManager.connection.startVPNTunnel(options: self.watf_configFTVprovider())
                            
                        } catch {
                            watf_complete?(false)
                        }
                        //                        }
                    }
                }
                
                watf_complete?(false)
                return
            }
            
            watf_manager.isEnabled = true
            self.watf_ftvManager = watf_manager
            watf_manager.saveToPreferences { err in
                if let _ = err {
                    watf_complete?(false)
                    return
                }
                
                watf_manager.loadFromPreferences { err in
                    if let _ = err {
                        watf_complete?(false)
                        return
                    }
                    do {
                        watf_complete?(true)
                        try watf_manager.connection.startVPNTunnel(options: self.watf_configFTVprovider())
                        
                    } catch {
                        watf_complete?(false)
                    }
                }
            }
        }
    }
    //MARK: - 取消连接
    func watf_stopConnect(watf_complete: ((Bool)->())? = nil) {
        watf_ftvAuthAction {watf_manager, watf_error in
            if let _ = watf_error {
                watf_complete?(false)
                return
            }
            watf_manager?.connection.stopVPNTunnel()
            watf_complete?(true)
        }
    }
    //MARK: - 连接 选中 节点
    func watf_connectSelectFTVAddress(watf_complete: ((Bool)->())? = nil) {
        let watf_ftvModel = watf_getSelectFTVModel()
        if watf_ftvCurStateType == .watf_connected {
            watf_ftvStateClickType = .watf_disAndConnect
            // 先取消连接
            watf_stopConnect { watf_state in
                
            }
            watf_curFTVModel = watf_ftvModel
            return
        }
        watf_curFTVModel = watf_ftvModel
        watf_ftvStateClickType = .watf_connect
        self.watf_startConnect(watf_ftvModel: watf_ftvModel, watf_complete: watf_complete)
    }
    //MARK: - add ftv noti
    @objc func watf_addFTVStateChangeNoti() {
        NotificationCenter.default.addObserver(
            forName: watf_ftvStateChange_noti,
            object: nil, queue: OperationQueue.main,
            using: {[weak self] watf_noti in
                guard let watf_self = self else { return }
                if let watf_session = watf_noti.object as? NETunnelProviderSession {
                    
                    if watf_self.watf_ftvStateClickType == .watf_connect { //如果点击了连接，只处理 连接中 和 连接成功
                        if watf_session.manager.connection.status == .connecting || watf_session.manager.connection.status == .connected {
                            // 如果已经返回连接， 则避免重复 重置点击状态
                            if watf_session.manager.connection.status == .connected {
                                watf_self.watf_ftvStateClickType = .watf_none
                                //                                self?.watf_funcAction(watf_customEvent: "per_lian_ong_pw")
                                //                                self?.watf_ftvIpExternalString = self?.watf_curFTVModel?.watf_address ?? ""
                            }
                            self?.watf_ftvChangeBlock?(WATFFTVStateType(rawValue: watf_session.manager.connection.status.rawValue) ?? .watf_invalid)
                            
                        }
                        return
                    }
                    if watf_self.watf_ftvStateClickType == .watf_disConnect { //如果点击了取消连接，只处理 取消连接中 和 取消连接成功
                        if watf_session.manager.connection.status == .disconnecting || watf_session.manager.connection.status == .disconnected {
                            // 如果已经返回取消连接， 则避免重复 重置点击状态
                            if watf_session.manager.connection.status == .disconnected {
                                watf_self.watf_ftvStateClickType = .watf_none
                                //                                self?.watf_funcAction(watf_customEvent: "per_no_ong_pw")
                                //                                WATFManager.watf_manager.watf_ftvIpExternalString = ""
                            }
                            self?.watf_ftvChangeBlock?(WATFFTVStateType(rawValue: watf_session.manager.connection.status.rawValue) ?? .watf_invalid)
                            
                        }
                        return
                    }
                    if watf_self.watf_ftvStateClickType == .watf_disAndConnect {
                        // 先提供断开
                        if watf_session.manager.connection.status == .disconnecting || watf_session.manager.connection.status == .disconnected {
                            
                            if watf_session.manager.connection.status == .disconnecting {
                                self?.watf_ftvChangeBlock?(WATFFTVStateType(rawValue: watf_session.manager.connection.status.rawValue) ?? .watf_invalid)
                                
                            }else {
                                //                                WATFManager.watf_manager.watf_ftvIpExternalString = ""
                                // 断开成功之后，开始连接
                                watf_self.watf_ftvStateClickType = .watf_connect
                                watf_self.watf_startConnect(watf_ftvModel: watf_self.watf_curFTVModel)
                            }
                            
                            
                        }
                    }
                }
                
            })
    }
    
}
// 更新 ftv 地址
extension WATFManager {
    // 这里没有 smart 连接，list1 随机选择一个放到 list2
    func watf_updateAllLocaFTVAddress(watf_saveType: NSInteger = 0,watf_startDate: NSInteger = 0, watf_ping: Bool = true) {
        if watf_saveType == 0 {
            watf_ftvModel1s.removeAll()
            watf_updateSmartFTVAddress(watf_startDate: watf_startDate)
            return
        }
        watf_ftvModels.removeAll()
        watf_updateFTVLoacalAddress(watf_startDate: watf_startDate)
    }
    func watf_updateSmartFTVAddress(watf_startDate: NSInteger = 0, watf_ping: Bool = true) {
        let watf_ftvModel = watf_getFTVRequestModel(watf_savePath: watf_ftvOne_key)
        if watf_ftvModel.watf_usTjc.watf_tsgme.count <= 0 {
            if watf_ping {
                //                self.watf_funcAction(watf_customEvent: "test_skw_yi_lach", watf_customDic: [
                //                    "perads": NSInteger(Date().timeIntervalSince1970)-watf_startDate,
                //                    "erweon":"nono"
                //                ])
            }
            watf_ftv1Done = true
            watf_configIpvListData()
            return
        }
        if watf_ftvModel.watf_usTjc.watf_uNeAY.count <= 0 {
            watf_ftv1Done = true
            watf_configIpvListData()
            return
        }
        self.watf_pingFTVAddressAction(watf_ftvReqModel: watf_ftvModel, watf_group: self.watf_pingGroup1, watf_queue: self.watf_pingQueue1, watf_ping: watf_ping) {[weak self] in
            self?.watf_ftv1Done = true
            let watf_models = watf_ftvModel.watf_usTjc.watf_tsgme.filter { watf_model in
                if !watf_ping {
                    return true
                }
                if self?.watf_ftvCurStateType == .watf_connected {
                    return true
                }
                return watf_model.watf_pingValue < 800
            }
            if watf_models.count == 0 {
                self?.watf_configIpvListData()
                return
            }
            
            let watf_count = watf_models.count
            let watf_ftvSerModel = watf_models[Int(arc4random_uniform(UInt32(watf_count)))]
            let watf_model =  self?.watf_createServerModel(watf_country:watf_ftvSerModel.watf_bCqRk,watf_address: watf_ftvSerModel.watf_hsQFu, watf_password: watf_ftvModel.watf_usTjc.watf_uNeAY, watf_port: Int64(watf_ftvModel.watf_usTjc.watf_pnEsK), watf_smart: true, watf_index: 0)
            watf_model?.watf_select = true
            self?.watf_smartFTVModel = watf_model
            
            for watf_model in watf_models {
                let watf_model = self?.watf_createServerModel(watf_country:watf_model.watf_bCqRk,watf_address: watf_model.watf_hsQFu, watf_password: watf_ftvModel.watf_usTjc.watf_uNeAY, watf_port: Int64(watf_ftvModel.watf_usTjc.watf_pnEsK), watf_ftvList: true, watf_index: 0)
                if let watf_model = watf_model {
                    self?.watf_ftvModel1s.append(watf_model)
                }
                
            }
            
            if watf_ping {
                //                self?.watf_funcAction(watf_customEvent: "test_skw_yi_lach", watf_customDic: [
                //                    "perads": NSInteger(Date().timeIntervalSince1970)-watf_startDate,
                //                    "erweon":"have"
                //                ])
            }
            self?.watf_configIpvListData()
        }
    }
    func watf_updateFTVLoacalAddress(watf_startDate: NSInteger = 0, watf_ping: Bool = true) {
        let watf_ftvModel = watf_getFTVRequestModel(watf_savePath: watf_ftvTwo_key)
        if watf_ftvModel.watf_usTjc.watf_tsgme.count <= 0 {
            if watf_ping {
                //                self.watf_funcAction(watf_customEvent: "test_pei_er_lac", watf_customDic: [
                //                    "perads": NSInteger(Date().timeIntervalSince1970)-watf_startDate,
                //                    "erweon":"nono"
                //                ])
            }
            watf_ftv2Done = true
            watf_configIpvListData()
            return
        }
        if watf_ftvModel.watf_usTjc.watf_uNeAY.count <= 0 {
            watf_ftv2Done = true
            watf_configIpvListData()
            return
        }
        self.watf_pingFTVAddressAction(watf_ftvReqModel: watf_ftvModel, watf_group: self.watf_pingGroup2, watf_queue: self.watf_pingQueue2, watf_ping: watf_ping) {[weak self] in
            self?.watf_ftv2Done = true
            let watf_models = watf_ftvModel.watf_usTjc.watf_tsgme.filter { watf_model in
                if !watf_ping {
                    return true
                }
                if self?.watf_ftvCurStateType == .watf_connected {
                    return true
                }
                return watf_model.watf_pingValue < 800
            }
            if watf_models.count == 0 {
                self?.watf_configIpvListData()
                return
            }
            // 删除旧的 所有地址
            
            var i:Int64 = 100
            for watf_model in watf_models {
                self?.watf_createServerModel(watf_country:watf_model.watf_bCqRk,watf_address: watf_model.watf_hsQFu, watf_password: watf_ftvModel.watf_usTjc.watf_uNeAY, watf_port: Int64(watf_ftvModel.watf_usTjc.watf_pnEsK), watf_ftvList: true, watf_index: i)
                i = i + 1
            }
            self?.watf_configIpvListData()
            NotificationCenter.default.post(name: watf_ftvLocalUpdate_noti, object: nil)
            if watf_ping {
                //                self?.watf_funcAction(watf_customEvent: "test_pei_er_lac", watf_customDic: [
                //                    "perads": NSInteger(Date().timeIntervalSince1970)-watf_startDate,
                //                    "erweon":"have"
                //                ])
            }
            
        }
    }
    //MARK: - 处理 ftv 列表
    func watf_configIpvListData() {
        WATFPrintOpt(watf_cot: "[WATF]FTVLIST==watf_ftv1Done==\(watf_ftv1Done)=watf_ftv2Done==\(watf_ftv2Done)=watf_ftvFireDone==\(watf_ftvFireDone)")
        if watf_ftv1Done && watf_ftv2Done && watf_ftvFireDone {
            if watf_ftvListConfig {
                return
            }
            watf_ftvListConfig = true
            if watf_ftvModel1s.count == 0 && watf_fireFTVModels.count != 0{
                let watf_count = watf_fireFTVModels.count
                watf_smartFTVModel = watf_fireFTVModels[Int(arc4random_uniform(UInt32(watf_count)))]
                watf_smartFTVModel?.watf_select = true
            }
            if watf_ftvModels.count == 0 && watf_ftvModel1s.count != 0{
                watf_ftvModels = watf_ftvModel1s
                
                let watf_count = watf_ftvModels.count
                watf_smartFTVModel = watf_ftvModels[Int(arc4random_uniform(UInt32(watf_count)))]
                watf_smartFTVModel?.watf_select = true
            }
            if watf_ftvModels.count == 0 && watf_ftvModel1s.count == 0 && watf_fireFTVModels.count != 0{
                watf_ftvModels = watf_fireFTVModels
                let watf_count = watf_ftvModels.count
                watf_smartFTVModel = watf_ftvModels[Int(arc4random_uniform(UInt32(watf_count)))]
                watf_smartFTVModel?.watf_select = true
            }
            // 获取本地ftv
            if watf_ftvModels.count == 0 {
                if watf_ftvModels.count == 0 {
                    // 使用本地服务器
                    let watf_model = watf_createServerModel()
                    watf_ftvModels.append(watf_model)
                }
            }
            watf_ftv1Done = false
            watf_ftv2Done = false
            watf_ftvRequest = false
            watf_ftvListConfig = false
        }
        
    }
    @objc func watf_pingFTVAddressAction(watf_ftvReqModel: WATFFTVRequestModel, watf_group: DispatchGroup, watf_queue: DispatchQueue, watf_ping:Bool = true,watf_complete:(()->())? = nil) {
        if self.watf_ftvCurStateType == .watf_connected {
            watf_complete?()
            return
        }
        if !watf_ping {
            watf_complete?()
        }
        if !watf_isCanNetWork() {
            watf_complete?()
            return
        }
        print("开始ping 节点==========================================")
        for watf_ftvModel in watf_ftvReqModel.watf_usTjc.watf_tsgme {
            watf_group.enter()
            watf_queue.async {
                if !WATFManager.watf_manager.watf_isCanNetWork() || self.watf_ftvCurStateType == .watf_connected {
                    watf_group.leave()
                    return
                }
                let pinger = try? WATFSwiftPingCom(host: watf_ftvModel.watf_hsQFu, configuration: PingConfiguration(interval: 0.5, with: 5), queue: watf_queue)
                pinger?.observer = { (response) in
                    let duration = response.duration
                    watf_ftvModel.watf_pingValue = NSInteger(duration*1000)
                    print("\(watf_ftvModel.watf_hsQFu) 节点ping结束==========================================\(NSInteger(duration*1000))")
                    
                }
                pinger?.finished = { _ in
                    print("\(watf_ftvModel.watf_hsQFu) 节点ping结束")
                    watf_group.leave()
                }
                pinger?.targetCount = 1
                try? pinger?.startPinging()
                
            }
        }
        
        watf_group.notify(queue: .main) {
            print("All pings are complete")
            watf_complete?()
        }
        
    }
}
//MARK: - save model
extension WATFManager {
    func watf_creadteDefaultFTVModel() {
        watf_defatulFTVModel = watf_createServerModel()
    }
    func watf_getFTVRequestModel(watf_savePath: String = watf_ftvOne_key) -> WATFFTVRequestModel {
        var watf_responseString = watf_getSrValue(watf_key: watf_savePath)
        if watf_responseString.count < 10 {
            return WATFFTVRequestModel()
        }
        watf_responseString = watf_responseString.watf_decodeBase64()?.watf_analyseFTVString() ?? ""
        guard let watf_ftvModel = WATFFTVRequestModel(JSONString: watf_responseString) else {
            return WATFFTVRequestModel()
        }
        return watf_ftvModel
    }
    @discardableResult func watf_createServerModel(watf_country:String = "Frankfurt", watf_address: String = "185.237.14.181", watf_password: String = "KcNSg2diQ1w#s8WA", watf_port: Int64 = 1229, watf_method: String = "chacha20-ietf-poly1305", watf_default: Bool = false, watf_smart: Bool = false, watf_ftvList: Bool = false, watf_index: Int64 = 0,watf_pingValue: NSInteger = 0) -> WATFFTVTempModel {
        let watf_ftvModel = WATFFTVTempModel()
        watf_ftvModel.watf_date = Date()
        watf_ftvModel.watf_address = watf_address
        watf_ftvModel.watf_password = watf_password
        watf_ftvModel.watf_port = watf_port
        watf_ftvModel.watf_method = watf_method
        watf_ftvModel.watf_default = watf_default
        watf_ftvModel.watf_country = watf_country
        watf_ftvModel.watf_smart = watf_smart
        watf_ftvModel.watf_ftvList = watf_ftvList
        watf_ftvModel.watf_icon = "watf_list_icon"
        watf_ftvModel.watf_index = watf_index
        watf_ftvModel.watf_pingValue = watf_pingValue
        if watf_country == "United States" || watf_country == "Atlanta"{
            watf_ftvModel.watf_icon = "watf_ftv_US"
        }
        if watf_country == "United Kingdom" {
            watf_ftvModel.watf_icon = "watf_ftv_GB"
        }
        if watf_country == "Canada" {
            watf_ftvModel.watf_icon = "watf_ftv_CA"
        }
        if watf_country == "France" {
            watf_ftvModel.watf_icon = "watf_ftv_FR"
        }
        if watf_country == "Japan" {
            watf_ftvModel.watf_icon = "watf_ftv_JP"
        }
        if watf_country == "Korea" {
            watf_ftvModel.watf_icon = "watf_ftv_KR"
        }
        if watf_country == "Frankfurt" || watf_country == "Germany" {
            watf_ftvModel.watf_icon = "watf_ftv_DE"
        }
        if watf_country == "Netherlands"  {
            watf_ftvModel.watf_icon = "watf_ftv_NL"
        }
        if watf_index != 0 {
            watf_ftvModels.append(watf_ftvModel)
        }
        return watf_ftvModel
    }
    func watf_getSelectFTVModel() -> WATFFTVTempModel? {
        if watf_smartFTVModel?.watf_select ?? false {
            return watf_smartFTVModel
        }
        let watf_model = watf_ftvModels.first { watf_ftvModel in
            return watf_ftvModel.watf_select == true
        }
        if let watf_model = watf_model {
            return watf_model
        }
        return watf_defatulFTVModel
    }
}
